<?php
namespace app\common\command;

use app\common\model\shop\ozon\OzonBrandModel;
use app\common\model\shop\ozon\OzonGoodsAttributeModel;
use app\common\model\shop\ozon\OzonGoodsCategoryModel;
use app\common\model\shop\ozon\OzonGoodsFeatureModel;
use app\common\model\shop\ozon\OzonGoodsFeatureValueModel;
use app\common\model\shop\ozon\OzonGoodsSkuModel;
use app\common\model\shop\PlatformModel;
use app\common\model\shop\ShopsModel;
use app\common\service\shop\Ozon;
use think\admin\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\facade\Db;
use think\facade\Log;

/**
 * OzonAttributeCommand
 * @Description
 * @author wangqinghui
 * @date 2024-11-18 09:59
 */
class OzonAttributeCommand extends Command
{

    protected $brand_attr_ids = [85, 31];
    /**
     * configure
     * @Description 配置
     * @author wangqinghui
     * @date 2024-11-18 10:14
     * @return void
     */
    protected function configure()
    {
        $this->setName('ozonAttribute')->addArgument('action', Argument::OPTIONAL, 'action', '')
        ->addArgument('paramId', Argument::OPTIONAL, 'category or account id', '')
        ->setDescription('sync pull ozon category and attribute and attribute value');
    }

    /**
     * execute
     * @param \think\console\Input $input
     * @param \think\console\Output $output
     * @Description
     * @author wangqinghui
     * @date 2024-11-18 10:33
     * @return void
     */
    protected function execute(Input $input, Output $output)
    {
        $action = trim($input->getArgument('action'));
        $action = strtolower($action);
        $param_id = $input->getArgument('paramId');
        switch ($action) {
            case 'category':// 分类
                $this->pullCategoryList();
                break;
            case 'attribute':// 属性
                $this->pullAttrList((int)$param_id);
                break;
            case 'brand':// 品牌
                $this->pullBrandList();
                break;
            case 'bindsku':// 同步商品sku
                $this->updateOzonSku($param_id);
                break;
            default:
                break;
        }
        $this->setQueueSuccess('action '.$action. ' end');
    }

    /**
     * 根据分类拉取分类下属性
     * @param integer $category_id
     * @Description
     * @author wangqinghui
     * @date 2024-11-19 15:20
     * @return void
     */
    protected function pullAttrList(int $category_id = 0)
    {
        if(empty($category_id)){
            // 获取所有分类
            $map = [
                ['status', '=', 0],
                ['level', '=', 3],
            ];
            $category_data = OzonGoodsCategoryModel::mk()->field('id,type_id,pid,name')->where($map)->select()->toArray();
        }else{
            $map = [
                ['id', '=', $category_id],
            ];
            $category_info = OzonGoodsCategoryModel::mk()->field('id,type_id,pid,name')->where($map)->find();
            if(empty($category_info)){
                $this->setQueueError('分类不存在');
            }
            $category_data = [$category_info->toArray()];
        }
        if(empty($category_data)){
            $this->setQueueSuccess('没有需要同步的分类');
        }
        
        $shop_info = $this->_getShopInfo();

        // 实例化ozon
        $config = [
            'client_id' => $shop_info['client_id'],
            'api_key' => $shop_info['api_key'],
        ];

        try {
            $ozon = new Ozon($config);
            foreach ($category_data as $key => $value) {
                $this->output->writeln('分类:'.$value['name'].' --start');
                // 获取分类下的属性
                $map = [
                    ['category_id',     '=',    $value['type_id']],
                ];
                $old_attribute_key_data = OzonGoodsFeatureModel::mk()->where($map)->column('id', 'feature_id');
                // 获取分类学的属性
                $attribute_ret = $ozon->getBrandByPages($value['pid'], $value['type_id']);
                if(empty($attribute_ret['code']) || ($attribute_ret['code'] != 1)){
                    $this->output->writeln('分类:'.$value['name'].' 获取属性失败:'.$ozon->getErr());
                    continue;
                }
                $attribute_arr = $attribute_ret['data'];
                if(empty($attribute_arr)){
                    $this->output->writeln('分类:'.$value['name'].'未获取到属性');
                    continue;
                }
                $limit = 100;
                $edit_attr_id_arr = [];
                foreach ($attribute_arr as $attr_k => $attr_v) {
                    $this->output->writeln('分类:'.$value['name'].' 属性:'.$attr_v['name'].' --start');
                    $input_type = 0;
                    // 获取平台属性ID
                    $feature_id = $attr_v['id'];
                    unset($attr_v['id']);
                    $attr_v['feature_id'] = $feature_id;
                    $attr_v['category_id'] = $value['type_id'];
                    $edit_attr_id = !empty($old_attribute_key_data[$feature_id]) ? $old_attribute_key_data[$feature_id] : 0;
                    if(!empty($edit_attr_id)){
                        OzonGoodsFeatureModel::mk()->where('id', $edit_attr_id)->update($attr_v);
                        $attr_id = $edit_attr_id;
                        $edit_attr_id_arr[$feature_id] = 1;
                    }else{
                        $attr_id = OzonGoodsFeatureModel::mk()->insertGetId($attr_v);
                    }
                    if(in_array($feature_id, $this->brand_attr_ids)){// 品牌不直接拉取
                        $input_type = 1;
                        $this->_dealBrandData($feature_id, $value);
                    }else{
                        $last_value_id = 0;
                        while(true){
                            // 获取属性值
                            $attribute_value_ret = $ozon->getAttributeByPages($feature_id, $value['pid'], $value['type_id'], $limit, $last_value_id);
                            if(empty($attribute_value_ret['code']) || ($attribute_value_ret['code'] != 1)){
                                $this->output->writeln('分类:'.$value['name'].' 属性:'.$attr_v['name'].' 获取属性值失败:'.$ozon->getErr());
                                break;
                            }
                            if(empty($attribute_value_ret['data'])){
                                $this->output->writeln('分类:'.$value['name'].' 属性:'.$attr_v['name'].' 属性值无数据');
                                break;
                            }
                            $attribute_value_result = $attribute_value_ret['data'];
                            $attribute_value_data = !empty($attribute_value_result['result']) ? $attribute_value_result['result'] : [];
                            $feature_value_ids = array_column($attribute_value_data, 'id');
                            // 获取原来的分类属性值
                            $map = [
                                ['feature_id', '=', $feature_id],
                                ['category_id', '=', $value['type_id']],
                                ['value_id', 'in', $feature_value_ids]
                            ];
                            $old_attribute_value_data = OzonGoodsFeatureValueModel::mk()->where($map)->column('id', 'value_id');
                            foreach ($attribute_value_data as $attr_value_key => $attr_value_value) {
                                $last_value_id = $attr_value_value['id'];
                                $input_type = 1;
                                $add_data = $attr_value_value;
                                $feature_value_id = $attr_value_value['id'];
                                unset($add_data['id']);
                                $edit_attr_value_id = !empty($old_attribute_value_data[$feature_value_id]) ? $old_attribute_value_data[$feature_value_id] : 0;
                                $add_data['description_category_id']    =   $value['pid'];
                                $add_data['category_id']    =   $value['type_id'];
                                $add_data['feature_id']    =   $feature_id;
                                $add_data['value_id']    =   $feature_value_id;
                                $add_data['info'] = mb_substr($attr_value_value['info'], 0, 300);// 截取部分描述
                                $add_data['value'] = mb_substr($attr_value_value['value'], 0, 200);// 截取部分描述
                                if(!empty($edit_attr_value_id)){
                                    OzonGoodsFeatureValueModel::mk()->where('id', $edit_attr_value_id)->update($add_data);
                                    $attr_value_id = $edit_attr_value_id;
                                }else{
                                    $attr_value_id = OzonGoodsFeatureValueModel::mk()->insertGetId($add_data);
                                }
                            }
                            if(empty($attribute_value_result['has_next'])){
                                $this->output->writeln('分类:'.$value['name'].' 属性:'.$attr_v['name'].' 属性值无下一页');
                                break;
                            }
                        }
                    }
                    
                    // 更新分类属性
                    $update_data = [
                        'feature_id'    => $feature_id,
                        'category_id'   => $value['type_id'],
                        'input_type'    => $input_type,
                        'description_category_id'   => $value['pid'],
                    ];
                    OzonGoodsFeatureModel::mk()->where('id', $attr_id)->update($update_data);
                    $this->output->writeln('分类:'.$value['name'].' 属性:'.$attr_v['name'].' --end');
                }
                // 删除无效属性
                $del_attr_ids = array_diff_key($old_attribute_key_data, $edit_attr_id_arr);
                if(!empty($del_attr_ids)){
                    OzonGoodsFeatureModel::mk()->where('id', 'in', $del_attr_ids)->delete();
                }
                $this->output->writeln('分类:'.$value['name'].' --end');
            }
        } catch (\Exception $th) {
            $this->setQueueError($th->getMessage());
        }
        $this->setQueueSuccess('同步属性完成');
    }

    /**
     * 拉取商品分类
     * @Description
     * @author wangqinghui
     * @date 2024-11-19 15:49
     * @return void
     */
    protected function pullCategoryList()
    {
        $shop_info = $this->_getShopInfo();
        // 实例化ozon
        $config = [
            'client_id' => $shop_info['client_id'],
            'api_key' => $shop_info['api_key'],
        ];
        $this->output->writeln('拉取分类 start');
        try {
            $ozon = new Ozon($config);
            $category_ret = $ozon->GetCategoryTree();
            if(empty($category_ret['code']) || ($category_ret['code'] != 1)){
                $this->output->writeln('获取分类失败:'.$ozon->getErr());
                return false;
            }
            $category_data = !empty($category_ret['data']) ? $category_ret['data'] : [];
            if(empty($category_data)){
                $this->output->writeln('拉取分类为空');
                return false;
            }
            $add_data = [];
            foreach ($category_data as $k => $v) {
                $add_data[] = [
                    'pid' => 0,
                    'type_id' => $v['description_category_id'] ?? ($v['type_id'] ?? 0),
                    'name' => $v['category_name'] ?? ($v['type_name'] ?? 0),
                    'status' => ($v['disabled'] == false) ? 0 : 1,
                    'level' => 1,
                    'path' => '0',
                ];
                if(!empty($v['children'])){
                    foreach ($v['children'] as $kk => $vv) {
                        $add_data[] = [
                            'pid' => $v['description_category_id'] ?? 0,
                            'type_id' => $vv['description_category_id'] ?? ($vv['type_id'] ?? 0),
                            'name' => $vv['category_name'] ?? ($vv['type_name'] ?? 0),
                            'status' => ($vv['disabled'] == false) ? 0 : 1,
                            'level' => 2,
                            'path' => '0/' . $v['description_category_id'],
                        ];
                        if(!empty($vv['children'])){
                            foreach ($vv['children'] as $kkk => $vvv) {
                                $add_data[] = [
                                    'pid' => $vv['description_category_id'] ?? 0,
                                    'type_id' => $vvv['description_category_id'] ?? ($vvv['type_id'] ?? 0),
                                    'name' => $vvv['category_name'] ?? ($vvv['type_name'] ?? 0),
                                    'status' => ($vvv['disabled'] == false) ? 0 : 1,
                                    'level' => 3,
                                    'path' => '0/' . $v['description_category_id'] . '/' . $vv['description_category_id'],
                                ];
                            }
                        }
                    }
                }
            }
            if(empty($add_data)){
                $this->output->writeln('没有需要操作的分类数据');
                return false;
            }
            $old_category_list = OzonGoodsCategoryModel::mk()->field('id,pid,type_id')->select()->toArray();
            $old_category_data = [];
            if(!empty($old_category_list)){
                foreach ($old_category_list as $key => $value) {
                    $old_category_data[$value['type_id'].$value['pid']] = $value['id'];
                }
            }
            foreach ($add_data as $key => $value) {
                $edit_id = !empty($old_category_data[$value['type_id'].$value['pid']]) ? $old_category_data[$value['type_id'].$value['pid']] : 0;
                if(!empty($edit_id)){
                    OzonGoodsCategoryModel::mk()->where('id', $edit_id)->update($value);
                }else{
                    $category_id = OzonGoodsCategoryModel::mk()->insertGetId($value);
                }
            }
        } catch (\Exception $th) {
            $this->setQueueError($th->getMessage());
        }
        // 缓存分类数据
        $map = [
            ['status', '=', 0],
        ];
        $category_list = OzonGoodsCategoryModel::mk()->where($map)->field('name title,id,pid,path,type_id')->select()->toArray();
        OzonGoodsCategoryModel::categoryTree($category_list);
        $this->output->writeln('拉取分类 end');
        $this->setQueueSuccess('同步分类完成');
    }

    /**
     * 获取店铺配置
     * @Description
     * @author wangqinghui
     * @date 2024-11-19 15:22
     * @return array
     */
    private function _getShopInfo(): array
    {
        // 获取ozon的平台ID
        $map = [
            ['status', '=', 1],
            ['code',     '=', PlatformModel::OZON_CODE]
        ];
        $platform_id = PlatformModel::mk()->where($map)->value('id');
        if(empty($platform_id)){
            $this->setQueueError('平台不存在');
        }
        // 获取店铺下ozon配置
        $map = [
            ['platform_id',  '=', $platform_id],
            ['status',   '=', 1],
            ['is_deleted',   '=', 0]
        ];
        $shop_info = ShopsModel::mk()->where($map)->find();
        if(empty($shop_info)){
            $this->setQueueError('店铺不存在');
        }
        return $shop_info->toArray();
    }

    /**
     * 拉取品牌数据
     * @Description
     * @author wangqinghui
     * @date 2024-12-10 16:29
     * @return void
     */
    protected function pullBrandList()
    {
        $shop_info = $this->_getShopInfo();
        // 实例化ozon
        $config = [
            'client_id' => $shop_info['client_id'],
            'api_key' => $shop_info['api_key'],
        ];
        $this->output->writeln('拉取品牌 start');
        // 获取常用品牌
        $map = [
            ['is_deleted',  '=', 0],
            ['status',  '=', 0],
        ];
        $brand_list = OzonBrandModel::mk()->where($map)->select()->toArray();
        if(empty($brand_list)){
            $this->output->writeln('没有需要同步的常用品牌');
            return true;
        }
        try {
            $ozon = new Ozon($config);
        } catch (\Exception $th) {
            $this->setQueueError($th->getMessage());
        }
        // 获取分类信息
        $category_ids = array_column($brand_list, 'category_id');
        if(empty($category_ids)){
            $this->setQueueError('品牌下没有分类数据');
        }
        $category_data = $brand_feature_data = [];
        $map = [
            ['type_id', 'in', $category_ids],
        ];
        $category_data = OzonGoodsCategoryModel::mk()->where($map)->column('pid,type_id,name', 'type_id');
        // 获取分类下品牌属性
        $map = [
            ['category_id', 'in', $category_ids],
            ['feature_id',  'in', $this->brand_attr_ids]
        ];
        $brand_feature_list = OzonGoodsFeatureModel::mk()->field('id,feature_id,category_id')->where($map)->select()->toArray();
        if(!empty($brand_feature_list)){
            foreach ($brand_feature_list as $key => $value) {
                $brand_feature_data[$value['category_id']][$value['feature_id']] = $value['id'];
            }
        }
        
        $limit = 1;
        foreach($brand_list as $key => $value){
            $pid = !empty($category_data[$value['category_id']]['pid']) ? $category_data[$value['category_id']]['pid'] : 0;
            $attr_id = !empty($brand_feature_data[$value['category_id']]) ? key($brand_feature_data[$value['category_id']]) : 85;
            $val_ret = $ozon->searchAttributeValue($attr_id, $pid, $value['category_id'], $value['name'], $limit);
            if(empty($val_ret['code']) || ($val_ret['code'] != 1)){
                $this->output->writeln('获取品牌名称失败:'.$ozon->getErr());
                continue;
            }
            $value_info = !empty($val_ret['data']['result'][0]) ? $val_ret['data']['result'][0] : [];
            if(!empty($value_info)){
                $update_data = [
                    'value_id'      =>  $value_info['id'],
                    'value'         =>  mb_substr($value_info['value'], 0, 200),
                    'info'          =>  mb_substr($value_info['info'], 0, 300),
                    'picture'       =>  $value_info['picture'] ?? '',
                    'status'        =>  1,
                ];
                $count = OzonBrandModel::mk()->where('id', $value['id'])->update($update_data);
                if($count >= 1){
                    unset($update_data['status']);
                    // 获取分类下品牌属性
                    $add_data = [];
                    if(!empty($brand_feature_data[$value['category_id']])){
                        foreach ($brand_feature_data[$value['category_id']] as $k => $v) {
                            $temp = [
                                'description_category_id'   =>  $pid,
                                'category_id'               =>  $value['category_id'],
                                'feature_id'                =>  $k,    
                            ];
                            $add_data[] = array_merge($temp, $update_data);
                        }
                    }
                    if(!empty($add_data)){
                        OzonGoodsFeatureValueModel::mk()->insertAll($add_data);
                    }
                }
            }
        }
        $this->output->writeln('拉取品牌 end');
        $this->setQueueSuccess('拉取品牌完成');
    }

    /**
     * 处理分类下属性品牌
     * @param integer $feature_id
     * @param array $category_info
     * @Description
     * @author wangqinghui
     * @date 2024-12-11 17:44
     * @return boolean
     */
    private function _dealBrandData(int $feature_id, array $category_info): bool
    {
        $map = [
            ['is_deleted',  '=', 0],
            ['status',  '=', 1],
            ['category_id', '=', $category_info['type_id']],
        ];
        $brand_list = OzonBrandModel::mk()->field('id,category_id,value_id,value,info,picture')->where($map)->select()->toArray();
        if(!empty($brand_list)){
            $brand_chunk_list = array_chunk($brand_list, 100);
            foreach ($brand_chunk_list as $key => $brand_chunk) {
                $brand_ids = array_column($brand_chunk, 'value_id');
                $old_brand_data = [];
                if(!empty($brand_ids)){
                    $map = [
                        ['feature_id', '=', $feature_id],
                        ['category_id', '=', $category_info['type_id']],
                        ['value_id', 'in', $brand_ids],
                    ];
                    $old_brand_data = OzonGoodsFeatureValueModel::mk()->where($map)->column('id', 'value_id');
                }
                $add_value_data = [];
                foreach ($brand_chunk as $key => $value) {
                    if(!empty($old_brand_data[$value['value_id']])){
                        $edit_id = $old_brand_data[$value['value_id']];
                        $update_data = [
                            'value'     =>  mb_substr($value['value'], 0, 200),
                            'info'      =>  mb_substr($value['info'], 0, 300),
                            'picture'   =>  $value['picture'] ?? '',
                        ];
                        OzonGoodsFeatureValueModel::mk()->where('id', $edit_id)->update($update_data);
                    }else{
                        $temp = [
                            'description_category_id'   =>  $category_info['pid'],
                            'category_id'               =>  $value['category_id'],
                            'feature_id'                =>  $feature_id,    
                            'value_id'                  =>  $value['value_id'],
                            'value'                     =>  mb_substr($value['value'], 0, 200),
                            'info'                      =>  mb_substr($value['info'], 0, 300),
                            'picture'                   =>  $value['picture'] ?? '',
                        ];
                        $add_value_data[] = $temp;
                    }
                }
                if(!empty($add_value_data)){
                    OzonGoodsFeatureValueModel::mk()->insertAll($add_value_data);
                }
            }
        }
        // 获取原来的分类属性值
        $map = [
            ['feature_id', '=', $feature_id],
            ['category_id', '=', $category_info['type_id']],
            ['value_id', '=', 126745801]// 无品牌
        ];
        $add_attr_value_data = [
            'description_category_id'       =>  $category_info['pid'],
            'category_id'                   =>  $category_info['type_id'],
            'feature_id'                    =>  $feature_id,
            'value_id'                      =>  126745801,
            'value'                         =>  '无品牌',
            'info'                          =>  'Товар не имеет бренда',
            'picture'                       =>  '',
        ];
        $old_attribute_value_data = OzonGoodsFeatureValueModel::mk()->where($map)->find();
        if(!empty($old_attribute_value_data)){
            OzonGoodsFeatureValueModel::mk()->where('id', $old_attribute_value_data['id'])->update($add_attr_value_data);
        }else{
            OzonGoodsFeatureValueModel::mk()->insertGetId($add_attr_value_data);
        }
        return true;
    }

    /**
     * 更新商品sku
     * @param string $goods_nu
     * @Description
     * @author wangqinghui
     * @date 2024-12-27 18:02
     * @return void
     */
    protected function updateOzonSku(string $goods_nu)
    {
        if(empty($goods_nu)){
            $this->setQueueSuccess('没有需要同步的商品sku');
            return true;
        }
        
        $map = [
            ['goods_nu',    '=', $goods_nu]
        ];
        $sku_info = OzonGoodsSkuModel::mk()->where($map)->find();
        if(empty($sku_info)){
            $this->setQueueSuccess('没有需要同步的商品sku');
            return true;
        }

        $shop_info = $this->_getShopInfo();
        // 实例化ozon
        $config = [
            'client_id' => $shop_info['client_id'],
            'api_key' => $shop_info['api_key'],
        ];
        // 获取商品ozonSku
        try {
            $ozon = new Ozon($config);
        } catch (\Exception $th) {
            $this->setQueueError($th->getMessage());
        }
        $goods_info_ret = $ozon->getProductInfo($sku_info['goods_nu'], $sku_info['product_id']);
        if(empty($goods_info_ret['code']) || ($goods_info_ret['code'] == 0)){
            $this->setQueueError('获取商品ozonSku失败:'.$ozon->getErr());
        }
        
        $goods_info = !empty($goods_info_ret['data']['result']) ? $goods_info_ret['data']['result'] : [];
        $update_data = ['ozon_sku'  =>  $goods_info['sku']];
        OzonGoodsSkuModel::mk()->where('id', $sku_info['id'])->update($update_data);
        $this->setQueueSuccess('更新ozon sku 成功');
    }
}